Set-Alias -Scope Global msbuild $Env:windir\Microsoft.NET\Framework\v4.0.30319\msbuild.exe

function Build-Project
{
	[CmdletBinding()] 
	param(
		[Parameter(ValueFromPipeline=$true)]
		[DTProject]$Project = (Get-ProjectFromFolder),
		[int]$Threads=(Get-LogicalProcessorCount),
		[switch]$LocalFeed=$LocalFeedOnly,
		[switch]$LocalFeedOnly)
		
	begin{
		$sourcesParam = Get-NugetSourcesParam -LocalFeedOnly:$LocalFeedOnly -LocalFeed:$LocalFeed
		$Builds = @()
		$IgnoredMSBuildOutputPattern = @('(^\[Microsoft .NET Framework, Version [0-9\.]*]$)',
										 '|(^Copyright \(C\) Microsoft Corporation 2007. All rights reserved.$)',	
										 '|(^Copyright \(C\) Microsoft Corporation. All rights reserved.$)',
										 '|(^Microsoft \(R\) Build Engine Version [0-9\.]*$)',
										 '|(^\s*$)') -join ''
										 
	   $MSBuildWarningsOutputPattern = @('(^.*warning (CS|MSB)[0-9]*:.*$)') -join ''
	}
	
	process 
	{	
		$SolutionPaths = @($Project.Solutions | foreach { $_.FullName })
		$Builds += @{
			"ScriptBlock" = {
				$SolutionPaths, $IgnoredMSBuildOutputPattern, $MSBuildWarningsOutputPattern = $args
				$SolutionPaths | foreach{
					$Solution = $_
					Write-Host -ForegroundColor Magenta "Results for $($Solution)"
					. $Env:windir\Microsoft.NET\Framework\v4.0.30319\msbuild.exe $Solution /m /verbosity:quiet /property:PackageSources="""$sourcesParam""" | 
						Where-Object { $_ -notmatch $IgnoredMSBuildOutputPattern } |
						ForEach-Object { 
							$_ | Where-Object { $_ -match $MSBuildWarningsOutputPattern } | 
								foreach { Write-Host $_ -ForegroundColor Yellow; Write-Host }
							$_  | Where-Object { $_ -notmatch $MSBuildWarningsOutputPattern } | 
								foreach { Write-Host $_ -ForegroundColor Red; Write-Host }
						}
				}
			};
			"Description" = "Building solutions in project $($Project.Name)";
			"ArgumentList" = @($SolutionPaths, $IgnoredMSBuildOutputPattern, $MSBuildWarningsOutputPattern);
		}
	}
	
	end{
		$Builds | Run-Threaded -Threads $Threads -Description "Build"
	}
}

function ReBuild-Project
{
	[CmdletBinding()] 
	param(
		[Parameter(ValueFromPipeline=$true)]
		[DTProject]$Project = $(Get-ProjectFromFolder),
		[int]$Threads=4,
		[switch]$LocalFeed=$LocalFeedOnly,
		[switch]$LocalFeedOnly,		
		[switch]$CleanNugetPackages)
		
	process
	{
		$Project | Clean-Project 
		$Project | Build-Project -LocalFeedOnly:$LocalFeedOnly -LocalFeed:$LocalFeed -Threads $Threads
	}
}

function Clean-Project
{
	[CmdletBinding()] 
	param(
		[Parameter(ValueFromPipeline=$true)]
		[DTProject]$Project = (Get-ProjectFromFolder),
		[int]$Threads=4,
		[switch]$CleanNugetPackages)
		
	begin{
		$sourcesParam = Get-NugetSourcesParam -LocalFeedOnly:$LocalFeedOnly -LocalFeed:$LocalFeed
		$ToRemove = @()
	}
		
	process
	{			
		if($Project.Solutions.Count -gt 0){						
			Write-Host -ForegroundColor Cyan "Finding folders to clean for $($Project.Directory)"
			$ToRemove += @(Get-ChildItem -Path $Project.Directory -Recurse -ErrorAction Continue | 
				Where {$_ -is [System.IO.DirectoryInfo]} |
				Where { $_.FullName -match '.*\\(((bin|obj)\\(debug|release))|(.*\.web\\bin))$' } |
				Sort-Object -Property FullName)
			
		
			if($CleanNugetPackages)
			{
				if(Test-Path "$($Project.Directory)\Packages\")
				{
					$ToRemove += @(Get-ChildItem -Path "$($Project.Directory)\Packages\" -ErrorAction Continue | 
						Where {$_ -is [System.IO.DirectoryInfo]} |
						Sort-Object -Property FullName)
				}
			}
		}
	}
	end{
		$RetryDeleteRecursive = {
						[CmdletBinding()] 
						param(
						[string]$FullName,
						[int]$Tries=5)
						Write-Verbose "Removing: $FullName"
						for($try=1; $try -le $Tries; $try++)
						{
							try
							{
								if(Test-Path $FullName)
								{
									Remove-Item -Recurse $FullName
								}
								break
							}catch
							{
								if($try -lt $Tries)
								{
									Write-Verbose "Retrying delete of $FullName"
									Start-Sleep -Milliseconds 100
									continue
								}
											
								$choices = [System.Management.Automation.Host.ChoiceDescription[]](
									(new-Object System.Management.Automation.Host.ChoiceDescription "&Retry","help"),
									(new-Object System.Management.Automation.Host.ChoiceDescription "&Cancel","help"),
									(new-Object System.Management.Automation.Host.ChoiceDescription "&IgnoreAndPray","help"))
								
								$answer = $host.ui.PromptForChoice("Failed to delete $FullName after $Tries tries!", 
																			  "What do you want to do??" ,
																			  $choices,
																			  0)		
								switch ($answer){
								    0 { AutoRetryRecursiveDelete $FullName $Tries }
								    1 { Write-Error "Failed to delete $FullName" }
									2 { break }
								}
							}
						}
					};
		
		Write-Host -ForegroundColor Cyan "Cleaning $($Project.Directory)"
		$ToRemove | foreach { & $RetryDeleteRecursive -FullName $_.FullName  }
	}
}

function Stop-MSBuild
{
	Get-Process MSBuild | Stop-Process
}